#ifndef SCRCPY_OPTIONS_H
#define SCRCPY_OPTIONS_H

/*
命令行参数解析成结构化的定义
*/

#include "common.h"

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "util/tick.h"

/* 
scrcpy的自定义日志级别，与SDL的日志级别对应。
本项目的日志打印也依赖SDL库
*/
enum sc_log_level {
    SC_LOG_LEVEL_VERBOSE,
    SC_LOG_LEVEL_DEBUG,
    SC_LOG_LEVEL_INFO,
    SC_LOG_LEVEL_WARN,
    SC_LOG_LEVEL_ERROR,
};

/* scrcpy录制文件格式，支持视频或音频 */
enum sc_record_format {
    // 枚举值默认从0开始
    /* 默认值：设置成自动不能正常录屏 */
    SC_RECORD_FORMAT_AUTO,
    SC_RECORD_FORMAT_MP4,
    SC_RECORD_FORMAT_MKV,
    SC_RECORD_FORMAT_M4A,
    SC_RECORD_FORMAT_MKA,
    SC_RECORD_FORMAT_OPUS,
    SC_RECORD_FORMAT_AAC,
    SC_RECORD_FORMAT_FLAC,
    SC_RECORD_FORMAT_WAV,
};

/**
 * 获取录制文件的格式是否为仅音频
 *
 */
static inline bool
sc_record_format_is_audio_only(enum sc_record_format fmt) {
    return fmt == SC_RECORD_FORMAT_M4A
        || fmt == SC_RECORD_FORMAT_MKA
        || fmt == SC_RECORD_FORMAT_OPUS
        || fmt == SC_RECORD_FORMAT_AAC
        || fmt == SC_RECORD_FORMAT_FLAC
        || fmt == SC_RECORD_FORMAT_WAV;
}

// 视频编解码器
enum sc_codec {
    SC_CODEC_H264,
    SC_CODEC_H265,
    SC_CODEC_AV1,
    SC_CODEC_OPUS,
    SC_CODEC_AAC,
    SC_CODEC_FLAC,
    SC_CODEC_RAW,
};

// Android设备的视频采集来源
enum sc_video_source {
    // Android屏幕
    SC_VIDEO_SOURCE_DISPLAY,
    // Android摄像头
    SC_VIDEO_SOURCE_CAMERA,
};

// Android设备的音频采集来源
enum sc_audio_source {
    // OUTPUT for video DISPLAY, MIC for video CAMERA
    SC_AUDIO_SOURCE_AUTO,
    SC_AUDIO_SOURCE_OUTPUT,
    SC_AUDIO_SOURCE_MIC,
    SC_AUDIO_SOURCE_PLAYBACK,
};

// 采集视频的摄像头
enum sc_camera_facing {
    SC_CAMERA_FACING_ANY,
    SC_CAMERA_FACING_FRONT,
    SC_CAMERA_FACING_BACK,
    SC_CAMERA_FACING_EXTERNAL,
};

                              // ,----- hflip (applied before the rotation)
                              // | ,--- 180°
                              // | | ,- 90° clockwise
                              // | | |
enum sc_orientation {         // v v v
    SC_ORIENTATION_0,         // 0 0 0
    SC_ORIENTATION_90,        // 0 0 1
    SC_ORIENTATION_180,       // 0 1 0
    SC_ORIENTATION_270,       // 0 1 1
    SC_ORIENTATION_FLIP_0,    // 1 0 0
    SC_ORIENTATION_FLIP_90,   // 1 0 1
    SC_ORIENTATION_FLIP_180,  // 1 1 0
    SC_ORIENTATION_FLIP_270,  // 1 1 1
};

static inline bool
sc_orientation_is_mirror(enum sc_orientation orientation) {
    assert(!(orientation & ~7));
    return orientation & 4;
}

// Does the orientation swap width and height?
static inline bool
sc_orientation_is_swap(enum sc_orientation orientation) {
    assert(!(orientation & ~7));
    return orientation & 1;
}

static inline enum sc_orientation
sc_orientation_get_rotation(enum sc_orientation orientation) {
    assert(!(orientation & ~7));
    return orientation & 3;
}

enum sc_orientation
sc_orientation_apply(enum sc_orientation src, enum sc_orientation transform);

static inline const char *
sc_orientation_get_name(enum sc_orientation orientation) {
    switch (orientation) {
        case SC_ORIENTATION_0:
            return "0";
        case SC_ORIENTATION_90:
            return "90";
        case SC_ORIENTATION_180:
            return "180";
        case SC_ORIENTATION_270:
            return "270";
        case SC_ORIENTATION_FLIP_0:
            return "flip0";
        case SC_ORIENTATION_FLIP_90:
            return "flip90";
        case SC_ORIENTATION_FLIP_180:
            return "flip180";
        case SC_ORIENTATION_FLIP_270:
            return "flip270";
        default:
            return "(unknown)";
    }
}

/* android设备的视频方向 */
enum sc_lock_video_orientation {
    // 默认值，不锁定视频方向
    SC_LOCK_VIDEO_ORIENTATION_UNLOCKED = -1,
    // lock the current orientation when scrcpy starts
    SC_LOCK_VIDEO_ORIENTATION_INITIAL = -2,
    SC_LOCK_VIDEO_ORIENTATION_0 = 0,
    SC_LOCK_VIDEO_ORIENTATION_90 = 3,
    SC_LOCK_VIDEO_ORIENTATION_180 = 2,
    SC_LOCK_VIDEO_ORIENTATION_270 = 1,
};

/* scrcpy键盘输入模式 */
enum sc_keyboard_input_mode {
    SC_KEYBOARD_INPUT_MODE_AUTO,
    SC_KEYBOARD_INPUT_MODE_UHID_OR_AOA, // normal vs otg mode
    SC_KEYBOARD_INPUT_MODE_DISABLED,
    SC_KEYBOARD_INPUT_MODE_SDK,
    SC_KEYBOARD_INPUT_MODE_UHID,
    SC_KEYBOARD_INPUT_MODE_AOA,
};

/* scrcpy鼠标输入模式 */
enum sc_mouse_input_mode {
    SC_MOUSE_INPUT_MODE_AUTO,
    SC_MOUSE_INPUT_MODE_UHID_OR_AOA, // normal vs otg mode
    SC_MOUSE_INPUT_MODE_DISABLED,
    SC_MOUSE_INPUT_MODE_SDK,
    SC_MOUSE_INPUT_MODE_UHID,
    SC_MOUSE_INPUT_MODE_AOA,
};

enum sc_gamepad_input_mode {
    SC_GAMEPAD_INPUT_MODE_DISABLED,
    SC_GAMEPAD_INPUT_MODE_UHID_OR_AOA, // normal vs otg mode
    SC_GAMEPAD_INPUT_MODE_UHID,
    SC_GAMEPAD_INPUT_MODE_AOA,
};

enum sc_mouse_binding {
    SC_MOUSE_BINDING_AUTO,
    SC_MOUSE_BINDING_DISABLED,
    SC_MOUSE_BINDING_CLICK,
    SC_MOUSE_BINDING_BACK,
    SC_MOUSE_BINDING_HOME,
    SC_MOUSE_BINDING_APP_SWITCH,
    SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
};

struct sc_mouse_binding_set {
    enum sc_mouse_binding right_click;
    enum sc_mouse_binding middle_click;
    enum sc_mouse_binding click4;
    enum sc_mouse_binding click5;
};

struct sc_mouse_bindings {
    struct sc_mouse_binding_set pri;
    struct sc_mouse_binding_set sec; // When Shift is pressed
};

/* 自定义按键注入模式 */
enum sc_key_inject_mode {
    // punctuation 标点符号
    // Inject special keys, letters and space as key events.
    // Inject numbers and punctuation as text events.
    // This is the default mode.
    SC_KEY_INJECT_MODE_MIXED,

    // Inject special keys as key events.
    // Inject letters and space, numbers and punctuation as text events.
    SC_KEY_INJECT_MODE_TEXT,

    // Inject everything as key events.
    SC_KEY_INJECT_MODE_RAW,
};

// 自定义快捷键模式，主要用于（程序启动后）热键的启动键。
// 因为可能有Alt+Shift+o 类似的快捷键，所以定义的位枚举
enum sc_shortcut_mod {
    /* 左ctrl键 =1,鼠标放在枚举上可以看到移位的运算结果 */
    SC_SHORTCUT_MOD_LCTRL = 1 << 0,
    /* 右ctrl键 =2 */
    SC_SHORTCUT_MOD_RCTRL = 1 << 1,
    /* 左alt键 =4 */
    SC_SHORTCUT_MOD_LALT = 1 << 2,
    /* 右alt键 =8 */
    SC_SHORTCUT_MOD_RALT = 1 << 3,
    /* 左super键 =16 */
    SC_SHORTCUT_MOD_LSUPER = 1 << 4,
    /* 右super键 =32 */
    SC_SHORTCUT_MOD_RSUPER = 1 << 5,
};

// 服务器与客户端通信用到的端口范围
struct sc_port_range {
    uint16_t first;
    uint16_t last;
};

// 自定义窗体位置-未定义模式，传入此值最后转为 SDL_WINDOWPOS_CENTERED
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)

/* scrcpy的启动配置信息，运行前配置，命令行传入参数 */
struct scrcpy_options {
    /**
     * 1.   手工指明的待连接的android设备的序列号。默认值为NULL。
     *      USB连接时，命令 adb devices可列出对应的序列号
     *  List of devices attached
            c7fa5fb2	device
            c7fa5fb2就是所谓的序列号
        2. IP：PORT 比如192.168.1.100:5555
     */
    const char *serial;
    // 设置裁剪显示区域，默认值为NULL
    const char *crop;
    // 录屏的视频记录到此文件中，可以是完整的路径。默认是NULL
    const char *record_filename;
    // 演示窗体的标题栏显示的名称。默认值为NULL，显示Android设备的型号
    const char *window_title;
     /* 推送到android设备的目标路径，默认值NULL，不设置时采用 DEFAULT_PUSH_TARGET 的定义 */
    const char *push_target;
     /* 默认值NULL,display 与 render_driver两个参数关联 */
    const char *render_driver;
    const char *video_codec_options;
    const char *audio_codec_options;
    const char *video_encoder;
    const char *audio_encoder;
    const char *camera_id;
    // 设置摄像头视频采集的分辨率，默认NULL
    const char *camera_size;
    // 设置摄像头采集摄像头的宽高比
    const char *camera_ar;
    uint16_t camera_fps;
    // 日志级别。默认的日志级别是 SC_LOG_LEVEL_INFO
    enum sc_log_level log_level;
    // 指定视频编解码器
    enum sc_codec video_codec;
    enum sc_codec audio_codec;
    // 设置视频来源，默认采集屏幕视频
    enum sc_video_source video_source;
    // 设置音频来源，
    enum sc_audio_source audio_source;
     // 录屏文件保存的视频格式，mp4或是mkv,默认值为SC_RECORD_FORMAT_AUTO
    enum sc_record_format record_format;
    // 键盘输入模式，默认值
    enum sc_keyboard_input_mode keyboard_input_mode;
    enum sc_mouse_input_mode mouse_input_mode;
    enum sc_gamepad_input_mode gamepad_input_mode;
    struct sc_mouse_bindings mouse_bindings;
    // 选择视频采集的摄像头
    enum sc_camera_facing camera_facing;
     /* DEFAULT_LOCAL_PORT_RANGE_FIRST 来自于app/meson.build文件中 */
    struct sc_port_range port_range;
    uint32_t tunnel_host;
    uint16_t tunnel_port;
     // 快捷键启动键，默认是左alt,左super。但是左super在ubuntu下没有生效。OR of enum sc_shortcut_mod values
    uint8_t shortcut_mods;
    // Android设备视频采集时的最大尺寸，横纵坐标中数值较大的取这个值
    uint16_t max_size;
    // 视频比特率，越大视频画质越好，但是画质越大传输延迟也越大
    uint32_t video_bit_rate;
    uint32_t audio_bit_rate;
    // 限制最大的FPS
    //uint16_t max_fps;
    // 锁定Android设备的视频方向
    const char *max_fps; // float to be parsed by the server
    enum sc_lock_video_orientation lock_video_orientation;
    // 设置视频方向
    enum sc_orientation display_orientation;
    // 设置记录方向
    enum sc_orientation record_orientation;
    // 设置窗体初始位置:x坐标,可设置 SC_WINDOW_POSITION_UNDEFINED for "auto"
    int16_t window_x;
    // 设置窗体初始位置:y坐标,可设置 SC_WINDOW_POSITION_UNDEFINED for "auto"
    int16_t window_y;
    // 设置窗体的初始宽度，默认是0，自动设置
    uint16_t window_width;
    // 设置窗体的初始高度，默认是0，自动设置
    uint16_t window_height;
    // Android设备多屏幕时，设置采集视频的屏幕
    uint32_t display_id;
    sc_tick display_buffer;
    sc_tick audio_buffer;
    sc_tick audio_output_buffer;
    sc_tick time_limit;
#ifdef HAVE_V4L2
   /* 虚拟摄像头设备？，设置了这个值也需要配置自定义解码器,默认为NULL */
    const char *v4l2_device;
    sc_tick v4l2_buffer;
#endif
#ifdef HAVE_USB
/* 是否开启了otg模式，默认值为false */
    bool otg;
#endif
    // 在Android设备上的物理触摸在PC窗体上展示出来，默认值为false
    bool show_touches;
    /* PC客户端窗体全屏显示，默认值是false */
    bool fullscreen;
    // PC客户端窗体是否在最上层，默认false
    bool always_on_top;
    /* 是否可以用鼠标键盘控制android设备,不显示客户端的窗体时即关闭控制，默认值为true */
    bool control;
    // 是否播放Android设备的视频图像，PC客户端仅显示一个图标。false采集但不播放
    bool video_playback;
    // 是否在PC客户端上播放音频，不影响视频或控制。默认是true。false采集但不播放
    bool audio_playback;
    // 启动时直接关闭Android设备的屏幕，默认是false
    bool turn_screen_off;
     // 默认值 SC_KEY_INJECT_MODE_MIXED
    enum sc_key_inject_mode key_inject_mode;
    // PC客户端窗体是否为无边框模式，默认false
    bool window_borderless;
    bool mipmaps;
    // Android设备一直保持常亮屏状态，屏幕会暗下来，但是不会锁屏，默认是false。
    bool stay_awake;
    bool force_adb_forward;
    // 是否关闭PC客户端的屏幕保护，默认为false
    bool disable_screensaver;
    bool forward_key_repeat;
    bool legacy_paste;
    // 是否在关闭scrcpy时自动关闭Android设备的屏幕，默认是false
    bool power_off_on_close;
    bool clipboard_autosync;
    bool downsize_on_error;
    // 是否启用了tcpip直连Android设备，不填IP：PORT时将尝试自动连接设备
    bool tcpip;
    // 启用TCPIP直连Android设备时，设备的IP[:PORT]
    const char *tcpip_dst;
    // 是否通过USB方式连接Android设备，默认false（如果只有一个Android设备通过USB连接PC时）
    bool select_usb;
    // 是否通过TCPIP方式连接Android设备，默认false（如果只有一个Android设备通过TCPIP连接PC时）
    bool select_tcpip;
    bool cleanup;
    // 是否在终端中实时打印fps，默认是false
    bool start_fps_counter;
    // 是否启动时开启Android设备的屏幕，默认true
    bool power_on;
    // 是否采集视频（可仅采集音频）默认为true
    bool video;
    // 是否音频转发，默认true，true则音频转发，并且不在PC上播放
    bool audio;
    // 是否强制开启音频转发，默认不强制开启，如果Android不支持音频转发时，scrcpy启动将报错，不能启动
    bool require_audio;
    bool kill_adb_on_close;
    bool camera_high_speed;
#define SC_OPTION_LIST_ENCODERS 0x1
#define SC_OPTION_LIST_DISPLAYS 0x2
#define SC_OPTION_LIST_CAMERAS 0x4
#define SC_OPTION_LIST_CAMERA_SIZES 0x8
    uint8_t list;
    // 是否显示PC客户端的窗体，默认为true
    bool window;
    bool mouse_hover;
    bool audio_dup;
};

// extern表明变量或者函数是定义在其他其他文件中的。在 option.c 中定义并初始化的变量
// const修饰的变量不能被修改，但是可以用指针修改内容
// scrcpy默认的启动参数
extern const struct scrcpy_options scrcpy_options_default;

#endif
